Server
启动后内存管理的底层原理与普通php-cli程序一致。具体请参考Zend VM
内存管理方面的文章。
在事件回调函数返回后,所有局部对象和变量会全部回收,不需要unset
。如果变量是一个资源类型,那么对应的资源也会被PHP底层释放。
function test()
{
$a = new Object;
$b = fopen('/data/t.log', 'r+');
$c = new swoole_client(SWOOLE_SYNC);
$d = new swoole_client(SWOOLE_SYNC);
global $e;
$e['client'] = $d;
}
$a
,$b
,$c
都是局部变量,当此函数return
时,这3
个变量会立即释放,对应的内存会立即释放,打开的IO资源文件句柄会立即关闭。$d
也是局部变量,但是return
前将它保存到了全局变量$e
,所以不会释放。当执行unset($e['client'])
时,并且没有任何其他PHP变量
仍然在引用$d
变量,那么$d
就会被释放。
在PHP
中,有3
类全局变量。
- 使用
global
关键词声明的变量 - 使用
static
关键词声明的类静态变量、函数静态变量 PHP
的超全局变量,包括$_GET
、$_POST
、$GLOBALS
等
全局变量和对象,类静态变量,保存在Server
对象上的变量不会被释放。需要程序员自行处理这些变量和对象的销毁工作。
class Test
{
static $array = array();
static $string = '';
}
function onReceive($serv, $fd, $reactorId, $data)
{
Test::$array[] = $fd;
Test::$string .= $data;
}
-
在事件回调函数中需要特别注意非局部变量的
array
类型值,某些操作如TestClass::$array[] = "string"
可能会造成内存泄漏,严重时可能发生爆内存,必要时应当注意清理大数组。 -
在事件回调函数中,非局部变量的字符串进行拼接操作是必须小心内存泄漏,如
TestClass::$string .= $data
,可能会有内存泄漏,严重时可能发生爆内存。
- 同步阻塞并且请求响应式无状态的
Server
程序可以设置max_request
和task_max_request
,当Worker
进程/Task
进程结束运行时或达到任务上限后进程自动退出。该进程的所有变量/对象/资源均会被释放回收。 - 程序内在
onClose
或设置定时器
及时使用unset
清理变量,回收资源
Swoole
提供的异步客户端与普通的PHP
变量不同,异步客户端在发起connect
时底层会增加一次引用计数,在连接close
时会减少引用计数。
包括
swoole_client
、swoole_mysql
、swoole_redis
、swoole_http_client
function test()
{
$client = new swoole_client(SWOOLE_TCP | SWOOLE_ASYNC);
$client->on("connect", function($cli) {
$cli->send("hello world\n");
});
$client->on("receive", function($cli, $data){
echo "Received: ".$data."\n";
$cli->close();
});
$client->on("error", function($cli){
echo "Connect failed\n";
});
$client->on("close", function($cli){
echo "Connection close\n";
});
$client->connect('127.0.0.1', 9501);
return;
}
$client
是局部变量,常规情况下return时会销毁。- 但这个
$client
是异步客户端在执行connect
时swoole引擎底层会增加一次引用计数,因此return时并不会销毁。 - 该客户端执行
onReceive
回调函数时进行了close
或者服务器端主动关闭连接触发onClose
,这时底层会减少引用计数,$client
才会被销毁。